import patchVnode from "./patchVnode";
import createElement from "./createElement";
// 判断是否是同一个虚拟节点
function isSameVnode(a, b) {
    return a.sel === b.sel && a.key === b.key;
}
export default function updateChildren(parentElm, oldCh, newCh) {
    console.log('我是updateChildren');
    console.log(oldCh, newCh);

    // 旧前
    let oldStartIdx = 0;
    // 新前
    let newStartIdx = 0;
    // 旧后
    let oldEndIdx = oldCh.length - 1;
    // 新后
    let newEndIdx = newCh.length - 1;
    // 旧前节点
    let oldStartVnode = oldCh[0];
    // 新前节点
    let newStartVnode = newCh[0];
    // 旧后节点
    let oldEndVnode = oldCh[oldEndIdx];
    // 新后节点
    let newEndVnode = newCh[newEndIdx];
    let keyMap = null;

    // 开始大while语句
    while(oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
        console.log('★');
        if (oldStartVnode == null || oldCh[oldStartIdx] == undefined) {
            oldStartVnode = oldCh[++oldStartIdx];
        } else if (oldEndVnode == null || oldCh[oldEndIdx] == undefined) {
            oldEndVnode = oldCh[--oldEndIdx];
        } else if (newStartVnode == null || newCh[newStartIdx] == undefined) {
            newStartVnode = newCh[++newStartIdx];
        } else if (newEndVnode == null || newCh[newEndIdx] == undefined) {
            newEndVnode = newCh[--newEndIdx];
        } else if (isSameVnode(oldStartVnode, newStartVnode)) {
            // 新前和旧前
            console.log('一 新前和旧前命中');
            patchVnode(oldStartVnode, newStartVnode);
            oldStartVnode = oldCh[++oldStartIdx];
            newStartVnode = newCh[++newStartIdx];
        } else if (isSameVnode(newEndVnode, oldEndVnode)) {
            // 新后和旧后
            console.log('二 新后和旧后命中');
            patchVnode(oldEndVnode, newEndVnode);
            oldEndVnode = oldCh[--oldEndIdx];
            newEndVnode = newCh[--newEndIdx];
        } else if (isSameVnode(newEndVnode, oldStartVnode)) {
            // 新后和旧前
            console.log('三 新后和旧前命中');
            patchVnode(oldStartVnode, newEndVnode);
            // 当 新后与旧前命中的时候，此时要移动节点。
            // 移动旧前指向的节点到老节点的旧后的后面
            // 如何移动节点？ 只要插入一个已经在DOM树上的节点，它就会移动
            parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling);
            newEndVnode = newCh[--newEndIdx];
            oldStartVnode = oldCh[++oldStartIdx];
        } else if (isSameVnode(newStartVnode, oldEndVnode)) {
            // 四 新前和旧后
            console.log('四 新前和旧后命中');
            patchVnode(oldEndVnode, newStartVnode);
            // 当 新前和旧后命中的时候，此时要移动节点。
            // 移动新前指向的节点到老节点的旧前的前面
            // 如何移动节点？ 只要插入一个已经在DOM树上的节点，它就会移动
            parentElm.insertBefore(newStartVnode.elm, oldStartVnode.elm);
            newStartVnode = newCh[++newStartIdx];
            oldEndVnode = oldCh[--oldEndIdx];
        } else {
            // 四个都没有命中
            // 寻找 key 的 map
            keyMap = {};
            for(let i = oldStartIdx; i < oldEndIdx; i++) {
                const key = oldCh[i].key;
                if (key !== undefined) {
                    keyMap[key] = i;
                }
            }
            // 寻找 newStartVnode 在 keyMap 中的位置
            const idxInOld = keyMap[newStartVnode.key];
            if (idxInOld) {
                // 存在，不是全新的项
                const elmToMove = oldCh[idxInOld];
                patchVnode(elmToMove, newStartVnode);
                // 把这项设置为 undefined，表示已经处理完了
                oldCh[idxInOld] = undefined;
                parentElm.insertBefore(elmToMove.elm, oldStartVnode.elm);
            } else {
                // 全新的项
                parentElm.insertBefore(createElement(newStartVnode), oldStartVnode.elm);
            }
            newStartVnode = newCh[++newStartIdx];
        }
    }
    // 继续看看有没有剩余的，循环结束了start还是小于end
    if (newStartIdx <= newEndIdx) {
        console.log('new 还有剩余节点没有处理, 要加项');
        for(let i = newStartIdx; i <= newEndIdx; i++) {
            // insertBefore可以自动识别 null, 如果是null就会自动排到队尾去，和 appendChild  是一致的
            parentElm.insertBefore(createElement(newCh[i]), oldCh[oldStartIdx].elm);
        }
    } else if (oldStartIdx <= oldEndIdx) {
        console.log('old 还有剩余节点没处理完，要删除项');
        for(let i = oldStartIdx; i <= oldEndIdx; i++) {
            if (oldCh[i]) {
                parentElm.removeChild(oldCh[i].elm);
            }
        }
    }
};

